package mypack.threadtest;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class BlockingQuery {

	private Object[] item;

	private int takeIndex, putIndex, count;

	private final ReentrantLock lock = new ReentrantLock();

	private Condition notFull = lock.newCondition();

	private Condition notEmpty = lock.newCondition();

	BlockingQuery(int cap) {
		if (cap <= 0) {
			throw new IllegalArgumentException("init error");
		}
		item = new Object[cap];
	}

	public void put(Object x) throws InterruptedException {

		lock.lock();
		try {
			while (count == item.length) {
				
				System.out.println("current count == "+ count + Thread.currentThread().getName()+ " is waiting to put  ....");
				
				notFull.await();
			}
			item[putIndex] = x;
			++count;
			if (++putIndex == item.length) {
				putIndex = 0;
			}
			System.out.println("current count == "+ count + " is signal others to take  ....");
			notEmpty.signal();
			
		} finally {
			lock.unlock();
		}

	}

	public Object take() throws InterruptedException {

		Object obj = null;
		lock.lock();
		try {
			while (count == 0) {
				
				System.out.println("current count == "+ count + Thread.currentThread().getName()+ " is waiting to take  ....");
				
				notEmpty.await();
			}
			obj = item[takeIndex];
			--count;
			if (++takeIndex == item.length) {
				takeIndex = 0;
			}
			System.out.println("current count == "+ count + " is signal others to put  ....");
			notFull.signal();
			return obj;
		} finally {
            lock.unlock();
		}

	}

}
